home *** CD-ROM | disk | FTP | other *** search
/ Isometric Game Programming with DirectX 7.0 / Isometric Game Programming.iso / source / chapter14 / isohex14_3 / isohex14_3.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-07-23  |  13.2 KB  |  521 lines

  1. /*****************************************************************************
  2. IsoHex14_3.cpp
  3. Ernest S. Pazera
  4. 11JUL2000
  5. Start a WIN32 Application Workspace, add in this file
  6. Requires ddraw.lib and dxguid.lib
  7. Needs DDFuncs.h/cpp, GDICanvas.h/cpp, and TileSet.h/cpp
  8. *****************************************************************************/
  9.  
  10. //////////////////////////////////////////////////////////////////////////////
  11. //INCLUDES
  12. //////////////////////////////////////////////////////////////////////////////
  13. #define WIN32_LEAN_AND_MEAN  
  14.  
  15. #include <windows.h>   
  16. #include "TileSet.h"
  17.  
  18. //////////////////////////////////////////////////////////////////////////////
  19. //DEFINES
  20. //////////////////////////////////////////////////////////////////////////////
  21. //name for our window class
  22. #define WINDOWCLASS "ISOHEX14"
  23. //title of the application
  24. #define WINDOWTITLE "IsoHex 14-3"
  25.  
  26. //map dimensions
  27. const int MAPWIDTH=40;
  28. const int MAPHEIGHT=40;
  29.  
  30. enum IsoDirection{
  31. ISO_NORTH=0,
  32. ISO_NORTHEAST=1,
  33. ISO_EAST=2,
  34. ISO_SOUTHEAST=3,
  35. ISO_SOUTH=4,
  36. ISO_SOUTHWEST=5,
  37. ISO_WEST=6,
  38. ISO_NORTHWEST=7
  39. };
  40.  
  41. //////////////////////////////////////////////////////////////////////////////
  42. //PROTOTYPES
  43. //////////////////////////////////////////////////////////////////////////////
  44. bool Prog_Init();//game data initalizer
  45. void Prog_Loop();//main game loop
  46. void Prog_Done();//game clean up
  47. POINT DiamondMap_TilePlotter(POINT ptMap,int iTileWidth,int iTileHeight);
  48. POINT DiamondMap_TileWalker(POINT ptStart,IsoDirection Dir);
  49. void SetUpSpaces();//sets up spaces
  50. void SetUpMap();
  51. void DrawMap();
  52. void ShowIsoCursor();
  53. void MoveCursor(IsoDirection Dir);
  54.  
  55. //////////////////////////////////////////////////////////////////////////////
  56. //GLOBALS
  57. //////////////////////////////////////////////////////////////////////////////
  58. HINSTANCE hInstMain=NULL;//main application handle
  59. HWND hWndMain=NULL;//handle to our main window
  60. LPDIRECTDRAW7 lpdd=NULL;//directdraw
  61. LPDIRECTDRAWSURFACE7 lpddsMain=NULL;//primary surface
  62. LPDIRECTDRAWSURFACE7 lpddsBack=NULL;//back buffer
  63. LPDIRECTDRAWCLIPPER lpddClipper=NULL;//clipper
  64. CTileSet tsIso;//tileset
  65. CTileSet tsCursor;//cursor
  66. int iTileMap[MAPWIDTH][MAPHEIGHT];
  67. POINT ptCursor;//cursor position
  68.  
  69. //spaces
  70. RECT rcWorldSpace;//worldspace
  71. RECT rcScreenSpace;//screen space(also, view space)
  72. RECT rcAnchorSpace;//anchor space
  73. POINT ptScreenAnchor;//screen anchor
  74.  
  75.  
  76. //////////////////////////////////////////////////////////////////////////////
  77. //WINDOWPROC
  78. //////////////////////////////////////////////////////////////////////////////
  79. LRESULT CALLBACK TheWindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
  80. {
  81.     //which message did we get?
  82.     switch(uMsg)
  83.     {
  84.     case WM_KEYDOWN:
  85.         {
  86.             //if escape hit, destroy window
  87.             if(wParam==VK_ESCAPE) DestroyWindow(hWndMain);
  88.             
  89.             //move cursor
  90.             if(wParam==VK_NUMPAD8)
  91.                 MoveCursor(ISO_NORTH);
  92.             if(wParam==VK_NUMPAD9)
  93.                 MoveCursor(ISO_NORTHEAST);
  94.             if(wParam==VK_NUMPAD6)
  95.                 MoveCursor(ISO_EAST);
  96.             if(wParam==VK_NUMPAD3)
  97.                 MoveCursor(ISO_SOUTHEAST);
  98.             if(wParam==VK_NUMPAD2)
  99.                 MoveCursor(ISO_SOUTH);
  100.             if(wParam==VK_NUMPAD1)
  101.                 MoveCursor(ISO_SOUTHWEST);
  102.             if(wParam==VK_NUMPAD4)
  103.                 MoveCursor(ISO_WEST);
  104.             if(wParam==VK_NUMPAD7)
  105.                 MoveCursor(ISO_NORTHWEST);
  106.             
  107.             
  108.             //handled, so return 0
  109.             return(0);
  110.         }break;
  111.     case WM_DESTROY://the window is being destroyed
  112.         {
  113.  
  114.             //tell the application we are quitting
  115.             PostQuitMessage(0);
  116.  
  117.             //handled message, so return 0
  118.             return(0);
  119.  
  120.         }break;
  121.     case WM_PAINT://the window needs repainting
  122.         {
  123.             //a variable needed for painting information
  124.             PAINTSTRUCT ps;
  125.             
  126.             //start painting
  127.             HDC hdc=BeginPaint(hwnd,&ps);
  128.  
  129.             /////////////////////////////
  130.             //painting code would go here
  131.             /////////////////////////////
  132.  
  133.             //end painting
  134.             EndPaint(hwnd,&ps);
  135.                         
  136.             //handled message, so return 0
  137.             return(0);
  138.         }break;
  139.     }
  140.  
  141.     //pass along any other message to default message handler
  142.     return(DefWindowProc(hwnd,uMsg,wParam,lParam));
  143. }
  144.  
  145.  
  146. //////////////////////////////////////////////////////////////////////////////
  147. //WINMAIN
  148. //////////////////////////////////////////////////////////////////////////////
  149. int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
  150. {
  151.     //assign instance to global variable
  152.     hInstMain=hInstance;
  153.  
  154.     //create window class
  155.     WNDCLASSEX wcx;
  156.  
  157.     //set the size of the structure
  158.     wcx.cbSize=sizeof(WNDCLASSEX);
  159.  
  160.     //class style
  161.     wcx.style=CS_OWNDC | CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
  162.  
  163.     //window procedure
  164.     wcx.lpfnWndProc=TheWindowProc;
  165.  
  166.     //class extra
  167.     wcx.cbClsExtra=0;
  168.  
  169.     //window extra
  170.     wcx.cbWndExtra=0;
  171.  
  172.     //application handle
  173.     wcx.hInstance=hInstMain;
  174.  
  175.     //icon
  176.     wcx.hIcon=LoadIcon(NULL,IDI_APPLICATION);
  177.  
  178.     //cursor
  179.     wcx.hCursor=LoadCursor(NULL,IDC_ARROW);
  180.  
  181.     //background color
  182.     wcx.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
  183.  
  184.     //menu
  185.     wcx.lpszMenuName=NULL;
  186.  
  187.     //class name
  188.     wcx.lpszClassName=WINDOWCLASS;
  189.  
  190.     //small icon
  191.     wcx.hIconSm=NULL;
  192.  
  193.     //register the window class, return 0 if not successful
  194.     if(!RegisterClassEx(&wcx)) return(0);
  195.  
  196.     //create main window
  197.     hWndMain=CreateWindowEx(0,WINDOWCLASS,WINDOWTITLE, WS_POPUP | WS_VISIBLE,0,0,320,240,NULL,NULL,hInstMain,NULL);
  198.  
  199.     //error check
  200.     if(!hWndMain) return(0);
  201.  
  202.     //if program initialization failed, then return with 0
  203.     if(!Prog_Init()) return(0);
  204.  
  205.     //message structure
  206.     MSG msg;
  207.  
  208.     //message pump
  209.     for(;;)    
  210.     {
  211.         //look for a message
  212.         if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  213.         {
  214.             //there is a message
  215.  
  216.             //check that we arent quitting
  217.             if(msg.message==WM_QUIT) break;
  218.             
  219.             //translate message
  220.             TranslateMessage(&msg);
  221.  
  222.             //dispatch message
  223.             DispatchMessage(&msg);
  224.         }
  225.  
  226.         //run main game loop
  227.         Prog_Loop();
  228.     }
  229.     
  230.     //clean up program data
  231.     Prog_Done();
  232.  
  233.     //return the wparam from the WM_QUIT message
  234.     return(msg.wParam);
  235. }
  236.  
  237. //////////////////////////////////////////////////////////////////////////////
  238. //INITIALIZATION
  239. //////////////////////////////////////////////////////////////////////////////
  240. bool Prog_Init()
  241. {
  242.     //set up ddraw
  243.     lpdd=LPDD_Create(hWndMain,DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT);
  244.     lpdd->SetDisplayMode(640,480,16,0,0);
  245.  
  246.     //set up primary surface
  247.     lpddsMain=LPDDS_CreatePrimary(lpdd,1);
  248.  
  249.     //set up back buffer
  250.     lpddsBack=LPDDS_GetSecondary(lpddsMain);
  251.  
  252.     //create clipper
  253.     lpdd->CreateClipper(0,&lpddClipper,NULL);
  254.     lpddClipper->SetHWnd(0,hWndMain);
  255.     lpddsBack->SetClipper(lpddClipper);
  256.  
  257.     //load in tileset
  258.     tsIso.Load(lpdd,"IsoHex14_3-1.bmp");
  259.     tsCursor.Load(lpdd,"IsoHex14_3-2.bmp");
  260.  
  261.     //set up spaces
  262.     SetUpSpaces();
  263.  
  264.     //set up the tilemap
  265.     SetUpMap();
  266.  
  267.     return(true);//return success
  268. }
  269.  
  270. //////////////////////////////////////////////////////////////////////////////
  271. //CLEANUP
  272. //////////////////////////////////////////////////////////////////////////////
  273. void Prog_Done()
  274. {
  275.     //clean up clipper
  276.     LPDDCLIP_Release(&lpddClipper);
  277.     //clean up primary surface
  278.     LPDDS_Release(&lpddsMain);
  279.     //clean up ddraw
  280.     LPDD_Release(&lpdd);
  281. }
  282.  
  283. //////////////////////////////////////////////////////////////////////////////
  284. //MAIN GAME LOOP
  285. //////////////////////////////////////////////////////////////////////////////
  286. void Prog_Loop()
  287. {
  288.     //clear out back buffer
  289.     DDBLTFX ddbltfx;
  290.     DDBLTFX_ColorFill(&ddbltfx,0);
  291.     lpddsBack->Blt(NULL,NULL,NULL,DDBLT_WAIT | DDBLT_COLORFILL,&ddbltfx);
  292.  
  293.     //show the board
  294.     DrawMap();
  295.  
  296.     //show the cursor
  297.     ShowIsoCursor();
  298.  
  299.     //flip
  300.     lpddsMain->Flip(NULL,DDFLIP_WAIT);
  301. }
  302.  
  303. POINT DiamondMap_TilePlotter(POINT ptMap,int iTileWidth,int iTileHeight)
  304. {
  305.     POINT ptReturn;
  306.     //calculate pixel position for the map position given
  307.     ptReturn.x=(ptMap.x-ptMap.y)*iTileWidth/2;
  308.     ptReturn.y=(ptMap.x+ptMap.y)*iTileHeight/2;
  309.     //return calculate point
  310.     return(ptReturn);
  311. }
  312.  
  313. void SetUpMap()
  314. {
  315.     //randomly set up the map
  316.     for(int x=0;x<MAPWIDTH;x++)
  317.     {
  318.         for(int y=0;y<MAPHEIGHT;y++)
  319.         {
  320.             iTileMap[x][y]=rand()%(tsIso.GetTileCount());
  321.         }
  322.     }
  323. }
  324.  
  325. void DrawMap()
  326. {
  327.     POINT ptTile;//tile pixel coordinate
  328.     POINT ptMap;//map coordinate
  329.     //get tile width and height
  330.     int iTileWidth=tsIso.GetTileList()[0].rcSrc.right-tsIso.GetTileList()[0].rcSrc.left;
  331.     int iTileHeight=tsIso.GetTileList()[0].rcSrc.bottom-tsIso.GetTileList()[0].rcSrc.top;
  332.     //the y loop is outside, because we must blit in horizontal rows
  333.     for(int y=0;y<MAPHEIGHT;y++)
  334.     {
  335.         for(int x=0;x<MAPWIDTH;x++)
  336.         {
  337.             //get pixel coordinate for map position
  338.             ptMap.x=x;
  339.             ptMap.y=y;
  340.             ptTile=DiamondMap_TilePlotter(ptMap,iTileWidth,iTileHeight);
  341.             //plot the tile(adjust for anchor)
  342.             tsIso.PutTile(lpddsBack,ptTile.x-ptScreenAnchor.x,ptTile.y-ptScreenAnchor.y,iTileMap[x][y]);
  343.         }
  344.     }
  345. }
  346.  
  347. void SetUpSpaces()
  348. {
  349.     //set up screen space
  350.     SetRect(&rcScreenSpace,0,0,640,480);
  351.     
  352.     //get a few metrics from the tileset
  353.     int iTileWidth=tsIso.GetTileList()[0].rcDstExt.right-tsIso.GetTileList()[0].rcDstExt.left;
  354.     int iTileHeight=tsIso.GetTileList()[0].rcDstExt.bottom-tsIso.GetTileList()[0].rcDstExt.top;
  355.  
  356.     //grab tile rectangle from tileset
  357.     RECT rcTile1;
  358.     RECT rcTile2;
  359.     RECT rcTile3;
  360.     RECT rcTile4;
  361.     RECT rcWS1;
  362.     RECT rcWS2;
  363.     POINT ptPlot;
  364.     POINT ptMap;
  365.  
  366.     //grab tiles from extents
  367.     CopyRect(&rcTile1,&tsIso.GetTileList()[0].rcDstExt);
  368.     CopyRect(&rcTile2,&tsIso.GetTileList()[0].rcDstExt);
  369.     CopyRect(&rcTile3,&tsIso.GetTileList()[0].rcDstExt);
  370.     CopyRect(&rcTile4,&tsIso.GetTileList()[0].rcDstExt);
  371.  
  372.     //move first tile to top position
  373.     ptMap.x=0;
  374.     ptMap.y=0;
  375.     ptPlot=DiamondMap_TilePlotter(ptMap,iTileWidth,iTileHeight);
  376.     OffsetRect(&rcTile3,ptPlot.x,ptPlot.y);
  377.  
  378.     //move first tile to bottom position
  379.     ptMap.x=MAPWIDTH-1;
  380.     ptMap.y=MAPHEIGHT-1;
  381.     ptPlot=DiamondMap_TilePlotter(ptMap,iTileWidth,iTileHeight);
  382.     OffsetRect(&rcTile2,ptPlot.x,ptPlot.y);
  383.  
  384.     //move first tile to left position
  385.     ptMap.x=0;
  386.     ptMap.y=MAPHEIGHT-1;
  387.     ptPlot=DiamondMap_TilePlotter(ptMap,iTileWidth,iTileHeight);
  388.     OffsetRect(&rcTile4,ptPlot.x,ptPlot.y);
  389.  
  390.     //move first tile to right position
  391.     ptMap.x=MAPWIDTH-1;
  392.     ptMap.y=0;
  393.     ptPlot=DiamondMap_TilePlotter(ptMap,iTileWidth,iTileHeight);
  394.     OffsetRect(&rcTile3,ptPlot.x,ptPlot.y);
  395.  
  396.     //combine these four tiles into world space
  397.     UnionRect(&rcWS1,&rcTile1,&rcTile2);
  398.     UnionRect(&rcWS2,&rcTile3,&rcTile4);
  399.     UnionRect(&rcWorldSpace,&rcWS1,&rcWS2);
  400.  
  401.     //copy worldspace to anchor space
  402.     CopyRect(&rcAnchorSpace,&rcWorldSpace);
  403.  
  404.     //subtract out screenspace
  405.     //adjust right edge
  406.     rcAnchorSpace.right-=(rcScreenSpace.right-rcScreenSpace.left);
  407.     //make sure right not less than left
  408.     if(rcAnchorSpace.right<rcAnchorSpace.left) rcAnchorSpace.right=rcAnchorSpace.left;
  409.     //adjust bottom edge
  410.     rcAnchorSpace.bottom-=(rcScreenSpace.bottom-rcScreenSpace.top);
  411.     //make sure bottom not less than top
  412.     if(rcAnchorSpace.bottom<rcAnchorSpace.top) rcAnchorSpace.bottom=rcAnchorSpace.top;
  413.  
  414.     //initialize screen anchor
  415.     ptScreenAnchor.x=0;
  416.     ptScreenAnchor.y=0;
  417.  
  418.     //initialize cursor
  419.     ptCursor.x=0;
  420.     ptCursor.y=0;
  421. }
  422.  
  423. POINT DiamondMap_TileWalker(POINT ptStart, IsoDirection Dir)
  424. {
  425.     switch(Dir)
  426.     {
  427.     case ISO_NORTH:
  428.         {
  429.             ptStart.x--;
  430.             ptStart.y--;
  431.         }break;
  432.     case ISO_NORTHEAST:
  433.         {
  434.             ptStart.y--;
  435.         }break;
  436.     case ISO_EAST:
  437.         {
  438.             ptStart.x++;
  439.             ptStart.y--;
  440.         }break;
  441.     case ISO_SOUTHEAST:
  442.         {
  443.             ptStart.x++;
  444.         }break;
  445.     case ISO_SOUTH:
  446.         {
  447.             ptStart.x++;
  448.             ptStart.y++;
  449.         }break;
  450.     case ISO_SOUTHWEST:
  451.         {
  452.             ptStart.y++;
  453.         }break;
  454.     case ISO_WEST:
  455.         {
  456.             ptStart.x--;
  457.             ptStart.y++;
  458.         }break;
  459.     case ISO_NORTHWEST:
  460.         {
  461.             ptStart.x--;
  462.         }break;
  463.     }
  464.     return(ptStart);
  465. }
  466.  
  467. void ShowIsoCursor()
  468. {
  469.     //copy cursor position
  470.     POINT ptMap=ptCursor;
  471.  
  472.     //get a few metrics from the tileset
  473.     int iTileWidth=tsIso.GetTileList()[0].rcDstExt.right-tsIso.GetTileList()[0].rcDstExt.left;
  474.     int iTileHeight=tsIso.GetTileList()[0].rcDstExt.bottom-tsIso.GetTileList()[0].rcDstExt.top;
  475.  
  476.     //plot cursor position
  477.     POINT ptPlot=DiamondMap_TilePlotter(ptMap,iTileWidth,iTileHeight);
  478.     
  479.     //put the cursor image
  480.     tsCursor.PutTile(lpddsBack,ptPlot.x-ptScreenAnchor.x,ptPlot.y-ptScreenAnchor.y,0);
  481. }
  482.  
  483. void MoveCursor(IsoDirection Dir)
  484. {
  485.     //move the cursor using the tilewalker
  486.     POINT ptTemp=DiamondMap_TileWalker(ptCursor,Dir);
  487.  
  488.     //get a few metrics from the tileset
  489.     int iTileWidth=tsIso.GetTileList()[0].rcDstExt.right-tsIso.GetTileList()[0].rcDstExt.left;
  490.     int iTileHeight=tsIso.GetTileList()[0].rcDstExt.bottom-tsIso.GetTileList()[0].rcDstExt.top;
  491.  
  492.     //bounds checking
  493.     //x<0
  494.     if(ptTemp.x<0) ptTemp=ptCursor;
  495.  
  496.     //y<0
  497.     if(ptTemp.y<0) ptTemp=ptCursor;
  498.  
  499.     //x>MAPWIDTH-1
  500.     if(ptTemp.x>(MAPWIDTH-1)) ptTemp=ptCursor;
  501.  
  502.     //y>MAPHEIGHT-1
  503.     if(ptTemp.y>(MAPHEIGHT-1)) ptTemp=ptCursor;
  504.  
  505.     //assign new cursor position
  506.     ptCursor=ptTemp;
  507.  
  508.     //do a test plot of the cursor(for centering)
  509.     POINT ptPlot=DiamondMap_TilePlotter(ptCursor,iTileWidth,iTileHeight);
  510.  
  511.     //center 
  512.     ptScreenAnchor.x=ptPlot.x-320+iTileWidth/2;
  513.     ptScreenAnchor.y=ptPlot.y-240+iTileHeight/2;
  514.  
  515.     //bounds checking for anchor.
  516.     if(ptScreenAnchor.x<rcAnchorSpace.left) ptScreenAnchor.x=rcAnchorSpace.left;
  517.     if(ptScreenAnchor.y<rcAnchorSpace.top) ptScreenAnchor.y=rcAnchorSpace.top;
  518.     if(ptScreenAnchor.x>rcAnchorSpace.right) ptScreenAnchor.x=rcAnchorSpace.right;
  519.     if(ptScreenAnchor.y>rcAnchorSpace.bottom) ptScreenAnchor.y=rcAnchorSpace.bottom;
  520. }
  521.